
module shiftRows
#(
  parameter DATA_WIDTH = 32
)(
 //OUTPUTS
  output [DATA_WIDTH - 1:0] col0_sft,   //Column 0 after shift row operation
  output [DATA_WIDTH - 1:0] col1_sft,   //Column 1 after shift row operation
  output [DATA_WIDTH - 1:0] col2_sft,   //Column 2 after shift row operation
  output [DATA_WIDTH - 1:0] col3_sft,   //Column 3 after shift row operation
 
 //INPUTS
 input [DATA_WIDTH - 1:0] col0,         //Column 0 of State Matrix
 input [DATA_WIDTH - 1:0] col1,         //Column 1 of State Matrix
 input [DATA_WIDTH - 1:0] col2,         //Column 2 of State Matrix
 input [DATA_WIDTH - 1:0] col3,         //Column 3 of State Matrix
 input enc_dec                          //Encryption-Decryption selection
);

localparam ST_WORD       = DATA_WIDTH/4;
localparam ST_LINE_WIDTH = 4;
localparam ST_COL_WIDTH  = 4;

wire [ST_WORD - 1:0] state[0:ST_LINE_WIDTH - 1][0:ST_COL_WIDTH - 1];
wire [ST_WORD - 1:0] state_sft[0:ST_LINE_WIDTH - 1][0:ST_COL_WIDTH - 1];

//=====================================================================================
// 1)  State Matrix generation
//=====================================================================================
generate
  genvar i;
  for(i = 0; i < ST_LINE_WIDTH; i = i + 1)
    begin
      assign state[i][0] = col0[ST_WORD*(i + 1) - 1:i*ST_WORD];
      assign state[i][1] = col1[ST_WORD*(i + 1) - 1:i*ST_WORD];
      assign state[i][2] = col2[ST_WORD*(i + 1) - 1:i*ST_WORD];
      assign state[i][3] = col3[ST_WORD*(i + 1) - 1:i*ST_WORD];
    end
endgenerate

//=====================================================================================
// 2)  Shift Row operation
//=====================================================================================
generate
  genvar l, c;
     for(l = 0; l < ST_LINE_WIDTH; l = l + 1)
        for(c = 0; c < ST_COL_WIDTH; c = c  + 1)
          begin
            assign state_sft[l][c] = enc_dec ? state[l][(l + c)%4] : state[l][(c + (4 - l))%4];
     end
endgenerate

//=====================================================================================
// 3)  State Matrix to Column transformation
//=====================================================================================
generate
  genvar k;
  for(k = 0; k < ST_LINE_WIDTH; k = k + 1)
    begin
      assign col0_sft[ST_WORD*(k + 1) - 1:k*ST_WORD] = state_sft[k][0];
      assign col1_sft[ST_WORD*(k + 1) - 1:k*ST_WORD] = state_sft[k][1];
      assign col2_sft[ST_WORD*(k + 1) - 1:k*ST_WORD] = state_sft[k][2];
      assign col3_sft[ST_WORD*(k + 1) - 1:k*ST_WORD] = state_sft[k][3];
    end
endgenerate

endmodule
